using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MyWebApi.Api.Entity;
using System;
using System.Collections.Generic;
using MyWebApi.Api.Db;


namespace MyWebApi.Api.Repository
{
    // BaseEntity是Entity里面所有数据表的父类，所有表都有继承BaseEntity表，
    // 所以在这给个where条件判断 让IRepository<T>通过泛型T结合在了一起，形成了耦合,
    // IRepository<T> 可以通过T操作IEntity
    // 而EfRepository<T>继承了IRepository<T>
    public class EfRepository<T> : IRepository<T> where T : BaseEntity
    {
        // 实例化一个数据库字段db
        private MyWebApiDb _db;

        public EfRepository(MyWebApiDb db){
            _db = db;
        }

        // 一个字段，没有任何属性 （get;set;)为自动属性
        private DbSet<T> _entity;

        // 设置一个字段（该字段是 _entity字段中自定义一个属性)
        protected DbSet<T> Entity
        {
            // 自己设置一个get属性
            get
            {
                // 当_entity字段等于空时(没有指定一个对象)
                if (_entity == null)
                {
                    // 从上下文重新获取一个
                    _entity = _db.Set<T>();
                }
                // 返回_entity，这时候的_entity有一个自定义属性
                return _entity;
            }
        }


        // 实现接口:开始实现IRepository<T>里面的接口成员(相当于给IRepository<T>里面的每一个接口写一个方法)
        public IQueryable<T> Table
        {
            get
            {
                // 返回将T赋值给了Entity
                return Entity.AsQueryable<T>();
            }
        }

        // 删除(指定T类型中的一个表进行操作(将T赋值给了Entity))指定id的数据
        public void Delete(int id)
        {
            // 查询出该数据
            var t = Entity.Where(x => x.Id == id).FirstOrDefault();
            // 删除该数据
            Entity.Remove(t);
            // 保存
            _db.SaveChanges();
        }


        // 根据id查询
        public T GetById(int id)
        {
            var t = Entity.Where(x => x.Id == id).FirstOrDefault();
            return t;
        }


        // 插入(entity传入用户输入的值)
        public void Insert(T entity)
        {
            // 用户传入的值为空时
            if (entity == null)
            {
                // 抛出错误
                throw new System.NullReferenceException();
            }

            // 这些是否启用，创建时间等是我们自己默认的，不是用户输入的
            entity.IsDeleted = false;
            entity.CreatedTime = DateTime.Now;
            entity.UpdatedTime = DateTime.Now;

            // 将entity的值都存入数据库
            Entity.Add(entity);
            // 保存
            _db.SaveChanges();

        }

        // 异步插入(entity传入用户输入的值)
        public async Task InsertAsync(T entity)
        {
            // 用户传入的值为空时
            if (entity == null)
            {
                // 抛出错误
                throw new System.NullReferenceException();
            }

            // 这些是否启用，创建时间等是我们自己默认的，不是用户输入的
            entity.IsDeleted = false;
            entity.CreatedTime = DateTime.Now;
            entity.UpdatedTime = DateTime.Now;
            entity.Remark = "暂无";

            // 将entity的值都异步存入数据库
            await Entity.AddAsync(entity);
            // 保存
            await _db.SaveChangesAsync();
        }

        // 批量插入若干数据
        public void InsertBulk(IEnumerable<T> entities)
        {

            // 循环要插入的数据
            foreach (var entity in entities)
            {
                // 这些是否启用，创建时间等是我们自己默认的，不是用户输入的
                entity.IsDeleted = false;
                entity.CreatedTime = DateTime.Now;
                entity.UpdatedTime = DateTime.Now;
                entity.Remark = "暂无";
            }
            // 批量添加
            Entity.AddRange(entities);
            // 保存
            _db.SaveChanges();

        }
        // 批量插入若干数据(异步)
        public async Task InsertBulkAsync(IEnumerable<T> entities)
        {
            // 循环要插入的数据
            foreach(var entity in entities){
                // 这些是否启用，创建时间等是我们自己默认的，不是用户输入的
                entity.IsDeleted = false;
                entity.CreatedTime = DateTime.Now;
                entity.UpdatedTime = DateTime.Now;
                entity.Remark = "暂无";
            }

            // 批量添加(异步)
            await Entity.AddRangeAsync(entities);
            // 保存
            await _db.SaveChangesAsync();
        }



        // 更新(entity用户传入的值)
        public void Update(T entity)
        {
            // 用户传入的值为空时
            if (entity == null)
            {
                // 抛出错误
                throw new NullReferenceException();
            }

            // 给entity给个更新的时间为当前时间
            entity.UpdatedTime = DateTime.Now;
            // 保存
            _db.SaveChanges();

        }

        // 批量更新若干数据
        public void UpdateBulk(IEnumerable<T> entities)
        {
            // 循环要更新的数据
            foreach (var entity in entities)
            {
                // 给entity给个更新的时间为当前时间
                entity.UpdatedTime = DateTime.Now;
            }


            // 保存
            _db.SaveChanges();
        }
    }

}